<script setup lang="ts">
import { onActivated, onDeactivated, nextTick } from 'vue'
import { ref, watch, computed } from "vue";
import { useRouter } from "vue-router";
import { getKeyBoard, setKeyBoard, getTetrisConfig, setTetrisConfig, showKeyBoardText, showTetrisConfigText, showTetrisHandlingText, getTetrisConfigRange, getSoundConfig, setSoundConfig, getUserConfig, setUserConfig, } from "@/utils/config"
import { ElMessage } from 'element-plus'
import { LangList } from '@/utils/i18n'
import { i18n } from '@/utils/i18n'
import {
    useScroll,
    useWindowSize,
} from '@vueuse/core'
import useAppStore from '@/pinia'
const app = useAppStore()
const router = useRouter()
import {
    isMobile,
} from "@/utils/utils"
import QRCode from 'qrcode'

const settingPageEl = ref(null)
const inputEl = ref(null)
const fromEl0 = ref(null)
const fromEl1 = ref(null)
const fromEl2 = ref(null)
const fromEl3 = ref(null)
const fromEl4 = ref(null)
const showMask = ref(false)
const lightAnchorIndex = ref(0)
const hasChangeAction = ref('')
let errorMessage = false as any
const qrCodeEl = ref(null)
const showQrCode = ref(false)
const isChannelAPlaying = ref(false) // 通道a是否在测试中
const isChannelBPlaying = ref(false) // 通道b是否在测试中
let channelATestTimer = null
let channelBTestTimer = null

const toIndex = () => {
    app.playSound('audio3')
    router.replace({
        path: `/`
    })
}


//  Particles start
import { spaceOptions } from "@/utils/particlesOptions";
let Options = spaceOptions() as any // 初始配置
const particlesHasInit = ref(false)
let container = null as any // 容器实例

const particlesLoaded = async (el) => {
    particlesHasInit.value = true
    container = el
}

//  Particles end

const controlList = ref([
    // {
    //     name: 'left',
    //     key: 'left'
    // }
])
const userConfigList = ref([])
const handlingList = ref([])
const soundSettingList = ref([])

const init = () => {
    // 存在键位冲突
    let hasConflict = false
    controlList.value = []
    const keyBoard = getKeyBoard()
    Object.keys(keyBoard).forEach((key) => {
        if (controlList.value.some((i: any) => i.key == keyBoard[key])) {
            hasConflict = true
        }
        controlList.value.push({
            name: key,
            key: keyBoard[key]
        })
    })

    handlingList.value = []
    const tetrisConfig = getTetrisConfig()
    Object.keys(tetrisConfig).forEach((key) => {
        handlingList.value.push({
            name: key,
            val: tetrisConfig[key]
        })
    })

    userConfigList.value = []
    const userConfig = getUserConfig()
    Object.keys(userConfig).forEach((key) => {
        userConfigList.value.push({
            name: key,
            val: userConfig[key]
        })
    })

    soundSettingList.value = []
    const soundConfig = getSoundConfig()
    Object.keys(soundConfig).forEach((key) => {
        soundSettingList.value.push({
            name: key,
            val: soundConfig[key]
        })
    })

    console.log('tetrisConfig', tetrisConfig)
    console.log('soundConfig', soundConfig)
    console.log('handlingList', handlingList)
    console.log('soundSettingList', soundSettingList)

    if (hasConflict) errorMessage = ElMessage.error('存在键位冲突，请重新设置')
    else if (errorMessage) errorMessage.close()
}

// 显示mask
const handleShowMask = (name) => {
    nextTick(() => {
        inputEl.value.focus()
    })
    showMask.value = true
    hasChangeAction.value = name
}

// 设置键位
const handleSetKeyBoard = (e) => {
    if (!showMask.value) return
    e.preventDefault()
    const code = e.code
    const name = hasChangeAction.value
    showMask.value = false
    setKeyBoard({
        [name]: code
    })
    init()
}

const anchorTo = (el) => {
    // 距离页面顶部的距离
    let distanceToTop = el.offsetTop
    const { y } = useScroll(settingPageEl, { behavior: 'smooth' })
    distanceToTop = distanceToTop - 20 // 上方预留空隙
    y.value = distanceToTop
}

const watchScroll = (e) => {
    if (settingPageEl.value) {
        let fromEl0Top = fromEl0.value.offsetTop
        let fromEl1Top = fromEl1.value.offsetTop
        let fromEl2Top = fromEl2.value.offsetTop
        let fromEl3Top = fromEl3.value.offsetTop
        let fromEl4Top = fromEl4.value.offsetTop
        const scrollTop = settingPageEl.value.scrollTop
        let fromEl0Abs = Math.abs(scrollTop - fromEl0Top)
        let fromEl1Abs = Math.abs(scrollTop - fromEl1Top)
        let fromEl2Abs = Math.abs(scrollTop - fromEl2Top)
        let fromEl3Abs = Math.abs(scrollTop - fromEl3Top)
        let fromEl4Abs = Math.abs(scrollTop - fromEl4Top)
        let min = Math.min(fromEl0Abs, fromEl1Abs, fromEl2Abs, fromEl3Abs, fromEl4Abs)
        let index = min == fromEl0Abs ? 0 : min == fromEl1Abs ? 1 : min == fromEl2Abs ? 2 : min == fromEl3Abs ? 3 : 4
        lightAnchorIndex.value = index
    }
}

const handleChange = (key, e) => {
    let config = getTetrisConfig()
    config[key] = Number(e.target.value)
    setTetrisConfig(config)
    init()
}

const handleUserConfigChange = (key, e) => {
    let config = getUserConfig()
    config[key] = key == 'autoPause' ? e : Number(e.target.value)
    setUserConfig(config)
    init()
}

const handleSoundChange = (key, e) => {
    let config = getSoundConfig()
    config[key] = key == 'BGM' || key == 'SOUND' ? e : Number(e.target.value)
    setSoundConfig(config)
    init()
    app.audioBase.changeVolume()
}

// 更改虚拟按键位置
const handleChangeVirtualButton = () => {
    router.push({
        path: '/settingVirtualButton',
    })
}

// 显示郊狼app二维码
const switchQrCode = (val: Boolean) => {
    if (val) {
        if (app.dgInfo.status) return // 已连接
        showQrCode.value = true
        app.dgInfo.onConnected = () => { // 扫码连接成功后关闭二维码
            switchQrCode(false)
        }
        nextTick(() => {
            const { height, width } = useWindowSize()
            let min = Math.min(height.value, width.value)
            let size = Math.floor(min * 0.6)
            const options = {
                width: size,  // 二维码的宽度
                height: size, // 二维码的高度
            }
            QRCode.toCanvas(qrCodeEl.value, app.dgInfo.qrCodeUrl, options, function (error) {
                if (error) {
                    console.error('二维码绘制失败', error);
                    showQrCode.value = false
                    app.showMessage('二维码绘制失败,请检查网络连接或刷新网页重试')
                }
            })
        })

    }
    else showQrCode.value = false
}

// 防抖
let debounceTimer = null
const handleStrengthChange = (channel: number, e: any, type: number) => {
    let val = Number(e.target.value)
    if (type === 1) {
        app.dgInfo.strength[channel - 1] = val
        if (debounceTimer) {
            clearTimeout(debounceTimer)
            debounceTimer = null
        }
        debounceTimer = setTimeout(() => {
            app.dgSetStrength(channel, val)
        }, 200)
        // 受伤时强度与游戏结束时强度不能低于一般强度
        if (app.dgInfo.damageStrength[channel - 1] < val) app.dgInfo.damageStrength[channel - 1] = val
        if (app.dgInfo.gameoverStrength[channel - 1] < val) app.dgInfo.gameoverStrength[channel - 1] = val
    }
    else if (type === 2) {
        app.dgInfo.damageStrength[channel - 1] = val
        if (app.dgInfo.strength[channel - 1] > val) app.dgInfo.strength[channel - 1] = val
        if (app.dgInfo.gameoverStrength[channel - 1] < val) app.dgInfo.gameoverStrength[channel - 1] = val
    }
    else if (type === 3) {
        app.dgInfo.gameoverStrength[channel - 1] = val
        if (app.dgInfo.strength[channel - 1] > val) app.dgInfo.strength[channel - 1] = val
        if (app.dgInfo.damageStrength[channel - 1] > val) app.dgInfo.damageStrength[channel - 1] = val
    }
}

const switchChannelTest = (channel: number, val: Boolean) => {
    if (channel == 1) {
        isChannelAPlaying.value = val
        if (val) {
            if (channelATestTimer) clearInterval(channelATestTimer)
            app.dgSendWave(1, 1)
            channelATestTimer = setInterval(() => {
                app.dgSendWave(1, 1) // a通道 持续1秒
            }, 2000)
        }
        else {
            clearInterval(channelATestTimer)
            channelATestTimer = null
        }
    }
    if (channel == 2) {
        isChannelBPlaying.value = val
        if (val) {
            if (channelBTestTimer) clearInterval(channelBTestTimer)
            app.dgSendWave(2, 1)
            channelBTestTimer = setInterval(() => {
                app.dgSendWave(2, 1) // a通道 持续1秒
            }, 2000)
        }
        else {
            clearInterval(channelBTestTimer)
            channelBTestTimer = null
        }
    }
}

const clearTestTimer = () => {
    if (channelATestTimer) {
        clearInterval(channelATestTimer)
        channelATestTimer = null
    }
    if (channelBTestTimer) {
        clearInterval(channelBTestTimer)
        channelBTestTimer = null
    }
}

// 计算属性 当前语言
const currentLang = computed(() => {
    return i18n.global.locale
})

const handleChangeLang = (e) => {
    let value = e.target.value || 'en'
    console.log('locale value', value);
    i18n.global.locale = value

    let config = getUserConfig()
    config['lang'] = value
    setUserConfig(config)
}

// 监听app.dgInfo.enable 关闭后销毁定时器
watch(() => app.dgInfo.enable, (newValue) => {
    if (!newValue) {
        clearTestTimer()
    }
})

onActivated(() => {
    if (container) {
        container.refresh()
        particlesHasInit.value = true
    }
    init()
    lightAnchorIndex.value = 0
    // 对settingPageEl监听滚动
    settingPageEl.value.addEventListener('scroll', watchScroll)

})

onDeactivated(() => {
    if (container) {
        container.pause()
        container.stop()
    }
    particlesHasInit.value = false
    // 移除监听
    settingPageEl.value.removeEventListener('scroll', watchScroll)
    // 停止测试
    isChannelAPlaying.value = false
    isChannelBPlaying.value = false
    clearTestTimer()
})


</script>

<template>
    <div class="settingPage hasScrollbar" ref="settingPageEl">
        <vue-particles :class="{ particlesShow: particlesHasInit }" id="pageSettingParticles" :options="Options"
            @particlesLoaded="particlesLoaded" />
        <div class="back flex items-center justify-center" @click="toIndex">{{ $t('setting.back') }}</div>

        <div class="from" ref="fromEl0">
            <div class="title">{{ $t('setting.config') }}</div>
            <div class="item flex items-center justify-between" v-for="(i, index) in userConfigList" :key="index">
                <div class="label">{{ showTetrisConfigText(i.name) }}</div>
                <switchInput v-if="i.name == 'autoPause'" :value="i.val"
                    @change="(e) => handleUserConfigChange(i.name, e)" />
                <select v-if="i.name == 'lang'" @change="handleChangeLang" :value="currentLang" class="select">
                    <option v-for="item in LangList" :key="item.value" :label="item[currentLang] || item.en"
                        :value="item.value" />
                </select>
            </div>
        </div>

        <div class="from" ref="fromEl1">
            <div class="title">{{ $t('setting.control') }}</div>
            <template v-if="isMobile()">
                <div class="item flex items-center justify-between" @click="handleChangeVirtualButton">
                    <div>{{ $t('setting.virtualButton') }}</div>
                    <div>{{ $t('setting.clickToChangePosition') }}</div>
                </div>
            </template>
            <template v-else>
                <div class="item flex items-center justify-between" v-for="(i, index) in controlList" :key="index"
                    @click="handleShowMask(i.name)">
                    <div>{{ showKeyBoardText(i.name) }}</div>
                    <div>{{ i.key }}</div>
                </div>
            </template>
        </div>

        <div class="from" ref="fromEl2">
            <div class="title">{{ $t('setting.handling') }}</div>
            <div class="item flex items-center justify-between" v-for="(i, index) in handlingList" :key="index">
                <div class="label">{{ showTetrisHandlingText(i.name) }}</div>
                <template v-if="i.name != 'autoPause'">
                    <input @input="(e) => handleChange(i.name, e)" :value="i.val" :min="getTetrisConfigRange(i.name)[0]"
                        :max="getTetrisConfigRange(i.name)[1]" class="range" type="range">
                    <div class="val">{{ i.val }}ms</div>
                </template>
                <switchInput :value="i.val" @change="(e) => handleChange(i.name, e)" v-else />
            </div>
        </div>

        <div class="from" ref="fromEl3">
            <div class="title">{{ $t('setting.sound') }}</div>
            <div class="item flex items-center justify-between" v-for="(i, index) in soundSettingList" :key="index">
                <div class="label">{{ i.name }}</div>
                <template v-if="i.name != 'BGM' && i.name != 'SOUND'">
                    <input @input="(e) => handleSoundChange(i.name, e)" :value="i.val" :min="0" :max="100" class="range"
                        type="range">
                    <div class="val">{{ i.val }}</div>
                </template>
                <switchInput :value="i.val" @change="(e) => handleSoundChange(i.name, e)" v-else />
            </div>
        </div>

        <div class="from" ref="fromEl4">
            <div class="title">{{ $t('setting.dglab') }}</div>
            <div class="item flex items-center justify-between">
                <div class="label">{{ $t('setting.enable') }}</div>
                <switchInput :value="app.dgInfo.enable" @change="() => app.dgSwitch()" />
            </div>
            <template v-if="app.dgInfo.enable">
                <div class="item flex items-center justify-between" @click="switchQrCode(true)">
                    <div class="label">{{ $t('setting.status') }}</div>
                    <div class="error" v-if="!app.dgInfo.connection">{{ $t('setting.networkError') }}</div>
                    <div v-else-if="app.dgInfo.status">{{ $t('setting.connected') }}</div>
                    <div v-else>{{ $t('setting.clickToConnect') }}</div>
                </div>
                <template v-if="app.dgInfo.status">
                    <div class="item flex items-center justify-between">
                        <div class="label">{{ $t('setting.channelA') }} {{ $t('setting.sortLimit') }}</div>
                        <div>{{ app.dgInfo.sort[0] }}</div>
                    </div>
                    <div class="item flex items-center justify-between">
                        <div class="label">{{ $t('setting.channelA') }} {{ $t('setting.gameStrength') }}</div>
                        <input @input="(e) => handleStrengthChange(1, e, 1)" :value="app.dgInfo.strength[0]" :min="0"
                            :max="app.dgInfo.sort[0]" class="range" type="range">
                        <div class="val">{{ app.dgInfo.strength[0] }}</div>
                    </div>
                    <div class="item flex items-center justify-between">
                        <div class="label">{{ $t('setting.channelA') }} {{ $t('setting.test') }}</div>
                        <switchInput :value="isChannelAPlaying" @change="(e) => switchChannelTest(1, e)" />
                    </div>

                    <div class="item flex items-center justify-between">
                        <div class="label">{{ $t('setting.channelB') }} {{ $t('setting.sortLimit') }}</div>
                        <div>{{ app.dgInfo.sort[1] }}</div>
                    </div>
                    <div class="item flex items-center justify-between">
                        <div class="label">{{ $t('setting.channelB') }} {{ $t('setting.gameStrength') }}</div>
                        <input @input="(e) => handleStrengthChange(2, e, 1)" :value="app.dgInfo.strength[1]" :min="0"
                            :max="app.dgInfo.sort[1]" class="range" type="range">
                        <div class="val">{{ app.dgInfo.strength[1] }}</div>
                    </div>
                    <div class="item flex items-center justify-between">
                        <div class="label">{{ $t('setting.channelB') }} {{ $t('setting.test') }}</div>
                        <switchInput :value="isChannelBPlaying" @change="(e) => switchChannelTest(2, e)" />
                    </div>
                </template>
            </template>
        </div>

        <div v-show="showMask" class="setKeyBoardMask" @click="() => showMask = false">
            {{ $t('setting.keyDown') }}
            <el-input class="input" ref="inputEl" autoFocus @keydown="handleSetKeyBoard" />
        </div>

        <div class="anchor">
            <div class="item" :class="{ light: lightAnchorIndex == 0 }" @click="anchorTo(fromEl0)">
                {{ $t('setting.config') }}
            </div>
            <div class="item" :class="{ light: lightAnchorIndex == 1 }" @click="anchorTo(fromEl1)">
                {{ $t('setting.control') }}
            </div>
            <div class="item" :class="{ light: lightAnchorIndex == 2 }" @click="anchorTo(fromEl2)">
                {{ $t('setting.handling') }}
            </div>
            <div class="item" :class="{ light: lightAnchorIndex == 3 }" @click="anchorTo(fromEl3)">
                {{ $t('setting.sound') }}
            </div>
            <div class="item" :class="{ light: lightAnchorIndex == 4 }" @click="anchorTo(fromEl4)">
                {{ $t('setting.dglab') }}
            </div>
        </div>

        <div class="qrCodeContainer flex items-center justify-center flex-col" v-if="showQrCode"
            @click="switchQrCode(false)">
            <div class="title">{{ $t('setting.qrCodeTitle') }}</div>
            <canvas ref="qrCodeEl" id="qrcode"></canvas>
        </div>

    </div>
</template>

<style lang="scss" scoped>
.settingPage {
    height: 100%;
    position: relative;
    background: #070709;
    padding: 10vmin 20vmin 10vmin 10vmin;
    box-sizing: border-box;
    overflow: auto;

    .anchor {
        position: fixed;
        right: 4vmin;
        top: 5vmin;

        .item {
            color: rgb(255, 255, 255, .5);
            font-size: 2vmin;
            padding: 1vmin 2vmin;
            border-radius: 1vmin;
            margin-top: 4vmin;
            cursor: pointer;
            transition: all 0.3s;
            text-align: center;
            letter-spacing: 0.1vmin;

            &:hover {
                color: #fff;
                background-color: rgba(0, 0, 0, 0.7);
            }

            &.light {
                position: relative;
                color: rgba(111, 155, 222, 0.8);

                &::after {
                    content: '';
                    position: absolute;
                    width: 80%;
                    height: 0.2vmin;
                    background-color: rgba(111, 155, 222, 0.4);
                    bottom: -2vmin;
                    left: 50%;
                    transform: translate(-50%, 0);
                }
            }
        }
    }

    #pageSettingParticles {
        width: 100%;
        height: 100%;
        position: absolute;
        top: 0;
        left: 0;
        pointer-events: none;
        z-index: 0;
        opacity: 0;
    }

    .particlesShow {
        animation: show 1s ease-in-out forwards;
    }

    @keyframes show {
        0% {
            opacity: 0;
        }

        100% {
            opacity: 0.8
        }
    }

    .back {
        position: fixed;
        top: 0;
        left: 0;
        width: 100%;
        height: 100%;
        max-width: 30vmin;
        border-right: 1px solid rgba(111, 155, 222, 0.1);
        color: hsl(0, 0%, 80%);
        font-size: 5vmin;
        cursor: pointer;
        border-radius: 1.5vmin;
        letter-spacing: 0.5vmin;
        transition: all 0.3s;
        z-index: 2;

        &:hover {
            color: #fff;
            border-right: 1px solid rgba(111, 155, 222, 0.4);
            max-width: 40vmin;
            background-color: rgba(111, 155, 222, 0.1);
            box-shadow: 0px 0px 24px 0px rgba(111, 155, 222, 0.4);
            letter-spacing: 4vmin;
        }
    }

    .from {
        background-image: linear-gradient(310deg, rgba(30, 46, 74, .8) 0%, rgba(16, 19, 32, .5) 100%);
        border-radius: 1vmin;
        margin: 0 0 0 30vmin;
        position: relative;
        padding: 5vmin 6vmin;
        box-sizing: border-box;
        backdrop-filter: blur(0.5vmin);
        margin-bottom: 10vmin;

        .title {
            color: rgb(0, 255, 255, .5);
            text-shadow: 0px 0px 2vmin rgba(255, 255, 255, 0.1);
            font-size: 4vmin;
            font-weight: bold;
            letter-spacing: 0.6vmin;
        }

        .item {
            background: rgba(111, 155, 222, 0.1);
            border: 1px solid rgba(111, 155, 222, 0.1);
            margin-top: 3vmin;
            border-radius: 0.5vmin;
            padding: 3vmin 4vmin;
            color: #677498;
            font-weight: 600;
            font-size: 3vmin;
            transition: all 0.5s;
            cursor: pointer;

            &:hover {
                background: rgba(111, 155, 222, 0.3);
                border: 1px solid rgba(111, 155, 222, 0.4);
                color: #fff;
                box-shadow: 0px 0px 24px 0px rgba(111, 155, 222, 0.4)
            }

            .range {
                flex: 1;
                -webkit-appearance: none;
                height: 2vmin;
                background: #e4e7ed;
                box-shadow: 0px 0px 0.5vmin 0.5vmin rgb(0, 0, 0, .1) inset;
                outline: none;
                opacity: 0.7;
                -webkit-transition: .2s;
                transition: opacity .2s;
                border-radius: 1vmin;
                cursor: pointer;

                &::-webkit-slider-thumb {
                    -webkit-appearance: none;
                    appearance: none;
                    width: 0;
                    min-width: 6vmin;
                    height: 4vmin;
                    background: rgb(72, 101, 146, .8);
                    box-shadow: 1px 1px 0.5vmin 1vmin rgb(0, 0, 0, .1);
                    cursor: pointer;
                    border-radius: 0.5vmin;
                    transition: all .3s;

                    &:hover {
                        min-width: 12vmin;
                        background: rgb(56, 82, 122);
                        border-radius: 1vmin;
                    }
                }
            }

            .label {
                min-width: 50vmin;
                flex-shrink: 0;
            }

            .error {
                font-size: 2vmin;
                color: #ff4343;
            }

            .val {
                min-width: 8vmin;
                flex-shrink: 0;
                text-align: center;
                color: #d7e3f6;
                font-weight: 400;
                font-size: 4vmin;
                margin-left: 2vmin;
            }

            .select {
                width: 40%;
                padding: 2vmin;
                border-radius: 1vmin;
                background: rgba(111, 155, 222, 0.1);
                outline: none;
            }

            option {
                color: #333
            }

        }
    }

    .setKeyBoardMask {
        position: fixed;
        z-index: 999999;
        top: 0;
        left: 0;
        width: 100vw;
        height: 100vh;
        background: rgb(0, 0, 0);
        display: flex;
        align-items: center;
        justify-content: center;
        color: #fff;
        font-size: 10vmin;
        letter-spacing: 2vmin;

        .input {
            opacity: 0;
            position: fixed;
            top: 0;
            left: 0
        }
    }

    .qrCodeContainer {
        width: 100%;
        height: 100%;
        position: fixed;
        top: 0;
        left: 0;
        z-index: 9999;
        background: #000000cc;
        opacity: 0;
        animation: show 0.5s ease-in-out forwards;

        .title {
            font-size: 3vmin;
            margin-bottom: 8vmin;
        }
    }

    @keyframes show {
        0% {
            opacity: 0;
        }

        100% {
            opacity: 1
        }
    }
}
</style>
